package com.wfh.frp.server;

import com.wfh.frp.coder.ProxMsgEncoder;
import com.wfh.frp.coder.ProxyMsgDecoder;
import com.wfh.frp.handler.ProxyClientHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import lombok.extern.slf4j.Slf4j;

/**
 * @Title: ProxyClientServer
 * @Author wangfenghuan
 * @Package com.wfh.frp.server
 * @Date 2025/10/8 13:29
 * @description: 客户端服务
 */
@Slf4j
public class ProxyClientServer {


    private static final EventLoopGroup group = new NioEventLoopGroup();

    /**
     * 启动客户端，要去链接服务端
     * @param serverHost
     * @param serverPort
     * @param targetHost
     * @param targetPort
     */
    public static void start(String serverHost, int serverPort, String targetHost, int targetPort){
        while (true) {
            try {
                Bootstrap serverBootstrap = new Bootstrap();
                serverBootstrap.group(group);
                serverBootstrap.channel(NioSocketChannel.class)
                        .option(ChannelOption.SO_KEEPALIVE, true)
                        .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
                        .handler(new ChannelInitializer<SocketChannel>() {
                            @Override
                            protected void initChannel(SocketChannel socketChannel) throws Exception {
                                socketChannel.pipeline()
                                         .addLast(new ProxyMsgDecoder())
                                         .addLast(new ProxMsgEncoder())
                                        // .addLast( new HttpObjectAggregator(65535))
                                        .addLast(new ProxyClientHandler(targetHost, targetPort));
                            }
                        });

                ChannelFuture sync = serverBootstrap.connect(serverHost, serverPort);
                sync.awaitUninterruptibly();

                if (sync.isSuccess()) {
                    log.info("Connected to server: {}:{}", serverHost, serverPort);
                    sync.channel().closeFuture().sync();
                    log.info("Connection closed, attempting to reconnect...");
                } else {
                    log.warn("Failed to connect to server: {}:{}, retrying in 3 seconds...", serverHost, serverPort);
                    Thread.sleep(3000);
                }
            } catch (Exception e) {
                log.error("Connection error: {}", e.getMessage());
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        }
        group.shutdownGracefully();
    }

}
